package com.nowcoder.community.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nowcoder.community.entity.LoginTicket;
import com.nowcoder.community.entity.User;
import org.springframework.util.DigestUtils;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class CommunityUtils {
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public static String generateUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String md5(String target) {
        if (target == null || target.length() <= 0) { return null; }
        return DigestUtils.md5DigestAsHex(target.getBytes(StandardCharsets.UTF_8));
    }

    public static String toJson(Object obj) throws JsonProcessingException {
        return objectMapper.writeValueAsString(obj);
    }

    public static <T> T parseJson(String json, Class<T> clazz) throws JsonProcessingException {
        return objectMapper.readValue(json, clazz);
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> parseJson(String json) throws JsonProcessingException {
        return objectMapper.readValue(json, HashMap.class);
    }

    public static LoginTicket createLoginTicket(User user, int expiredMinute) {
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setTicket(CommunityUtils.generateUUID());
        loginTicket.setUserId(user.getId());
        loginTicket.setExpired(new Date(System.currentTimeMillis() + 1000L * 60 * expiredMinute));
        loginTicket.setStatus(0);
        return loginTicket;
    }

    /**
     * 将cookie添加到modelAndView以便让ModelCookieInterceptor将cookie设置到response
     * Add cookie to modelAndView and let ModelCookieInterceptor to set cookie to the response
     * @see com.nowcoder.community.controller.interceptor.ModelCookieInterceptor
     */
    public static void addCookie(ModelAndView modelAndView, Cookie cookie) {
        @SuppressWarnings("unchecked")
        List<Cookie> cookieList = (List<Cookie>) modelAndView.getModel().getOrDefault("cookies", new ArrayList<Cookie>());
        cookieList.add(cookie);
        modelAndView.addObject("cookies", cookieList);
    }

    public static Cookie getCookie(HttpServletRequest req, String name) {
        if (req != null) {
            for (Cookie cookie : req.getCookies()) {
                if (Objects.equals(cookie.getName(), name)) {
                    return cookie;
                }
            }
        }
        return null;
    }

    public static String getCookieValue(HttpServletRequest req, String name) {
        Cookie cookie = CommunityUtils.getCookie(req, name);
        return cookie == null ? null : cookie.getValue();
    }

    public static String generateSalt() {
        return CommunityUtils.generateUUID().substring(0, 5);
    }

    public static String encodePassword(String password, String salt) {
        return CommunityUtils.md5(password + salt);
    }

    public static String getFilenameSuffix(String filename) {
        if (filename == null) { return null; }
        return filename.substring(filename.lastIndexOf('.'));
    }

    public static BufferedReader getResourceFileReader(String filename) throws IOException {
        InputStream is = CommunityUtils.class.getClassLoader().getResourceAsStream(filename);
        if (is != null) {
            InputStreamReader isr = new InputStreamReader(is);
            return new BufferedReader(isr);
        }
        return null;
    }

    public static Integer getFormId(String conversationId) {
        if (conversationId != null && !conversationId.isEmpty()) {
            String[] strings = conversationId.split("_");
            if (strings.length != 2) {
                return null;
            }
            return Integer.valueOf(strings[1]);
        }
        return null;
    }

    public static Integer getToId(String conversationId) {
        if (conversationId != null && !conversationId.isEmpty()) {
            String[] strings = conversationId.split("_");
            if (strings.length != 2) {
                return null;
            }
            return Integer.valueOf(strings[0]);
        }
        return null;
    }

    public static String getConversationId(int fromId, int toId) {
        return fromId < toId ? fromId + "_" + toId : toId + "_" + fromId;
    }
}
